<?php
/*
 *
 * This class implements all the features of VKontakte Server API
 */
class Api {
	// api_id
	public $api_id = null;
	// secret key
	public $api_secret = null;
	// version
	public $v = "2.0";
	// format
	public $format = "JSON";
	// server
	public $server = "http://api.vkontakte.ru/api.php";
	// last error here 
	public $error;
	
	
	function Api($api_id, $api_secret) {
		$this->api_id = $api_id;
		$this->api_secret = $api_secret;
	}

    private function makeSiganture(&$params) {
		$sorted_array = array();
		foreach ($params as $k => $v) {
			$sorted_array[] = $k . "=" . $v;
		}
		sort($sorted_array, SORT_STRING);
		
		return md5(join("", $sorted_array) . $this->api_secret);
	}
	
	private function fillCommonParams(&$params){
		$params['v'] = $this->v;
		$params['format'] = $this->format;
		$params['api_id'] = $this->api_id;
		$params['timestamp'] = time();
		$params['random'] = rand();
		$params['sig'] = $this->makeSiganture($params);
	}

    public function isAuthorizedCall($auth_key, $viewer_id) {
        return $auth_key == md5($this->api_id . "_" . $viewer_id . "_" . $this->api_secret);
    }

    public function addRating($uid, $rate, $message = null) {
        $params = array();
        $params['method'] = "secure.addRating";
        $params['uid'] = $uid;
        $params['rate'] = $rate;
        if (!empty($message)) {
            $params['message'] = $message;
        }
        $this->fillCommonParams($params);

        $response = json_decode($this->request($params));

		if (!empty($response->error)) {
			$this->error = $response->error->error_msg;
			return null;
		}
        return true;
    }

    public function setCounter($uid, $counter) {
        $params['method'] = "secure.setCounter";
        $params['uid'] = $uid;
        $params['counter'] = $counter;

        $this->fillCommonParams($params);

        $response = json_decode($this->request($params));

		if (!empty($response->error)) {
			$this->error = $response->error->error_msg;
			return null;
		}
        return true;
    }
    
	public function getAppBalanse() {
		$params = array();
		$params['method'] = "secure.getAppBalance";
		
		$this->fillCommonParams($params);
		$response = json_decode($this->request($params));
	
		if (!empty($response->error)) {
			$this->error = $response->error->error_msg;
			return null;
		}
		return (int)$response->response;
	}
	
	public function sendNotification($uids, $message) {
		$params = array();
		$params['method'] = "secure.sendNotification";
		$params['uids'] = join(",", $uids);
		$params['message'] = $message;
		
		$this->fillCommonParams($params);
		$json = $this->request($params);
		$response = json_decode($json);
	
		if (!empty($response->error)) {
			$this->error = $response->error->error_msg;
			return null;
		}
		return split(",", $response->response);
	}
	
	public function saveAppStatus($uid, $status) {
		$params = array();
		$params['method'] = "secure.saveAppStatus";
		$params['uid'] = $uid;
		$params['status'] = $status;
		
		$this->fillCommonParams($params);
		$json = $this->request($params);
		$response = json_decode($json);
	
		if (!empty($response->error)) {
			$this->error = $response->error->error_msg;
			return null;
		}
		return $response->response;
	}
	
	public function getAppStatus($uid) {
		$params = array();
		$params['method'] = "secure.getAppStatus";
		$params['uid'] = $uid;
		
		$this->fillCommonParams($params);
		$json = $this->request($params);
		$response = json_decode($json);
	
		if (!empty($response->error)) {
			$this->error = $response->error->error_msg;
			return null;
		}
		return $response->response;
	}
	
	public function getBalanse($uid) {
		$params = array();
		$params['method'] = "secure.getBalance";
		$params['uid'] = $uid;
		
		$this->fillCommonParams($params);
		$json = $this->request($params);
		$response = json_decode($json);
	
		if (!empty($response->error)) {
			$this->error = $response->error->error_msg;
			return null;
		}
		return (int)$response->response;		
	}
	
	public function addVotes($uid, $count) {
		$params = array();
		$params['method'] = "secure.addVotes";
		$params['uid'] = $uid;
		$params['votes'] = $count;
		
		$this->fillCommonParams($params);
		$json = $this->request($params);
		$response = json_decode($json);
	
		if (!empty($response->error)) {
			$this->error = $response->error->error_msg;
			return null;
		}
		return (int)$response->response;		
	}
	
	public function withdrawVotes($uid, $count) {
		$params = array();
		$params['method'] = "secure.withdrawVotes";
		$params['uid'] = $uid;
		$params['votes'] = $count;
		
		$this->fillCommonParams($params);
		$json = $this->request($params);
		$response = json_decode($json);
	
		if (!empty($response->error)) {
			$this->error = $response->error->error_msg;
			return null;
		}
		return (int)$response->response;		
	}
	
	public function transferVotes($from, $to, $count) {
		$params = array();
		$params['method'] = "secure.transferVotes";
		$params['uid_from'] = $from;
		$params['uid_to'] = $to;
		$params['votes'] = $count;
		
		$this->fillCommonParams($params);
		$json = $this->request($params);
		$response = json_decode($json);
	
		if (!empty($response->error)) {
			$this->error = $response->error->error_msg;
			return null;
		}
		return (int)$response->response;		
	}
	
	public function getTransactionsHistory($type, $from, $to, $from_date, $to_date, $limit = 1000) {
		$params = array();
		$params['method'] = "secure.getTransactionsHistory";
		$params['uid_from'] = $from;
		$params['uid_to'] = $to;
		$params['type'] = $type;
		$params['date_from'] = $from_date;
		$params['date_to'] = $to_date;
		$params['limit'] = $limit;
		
		$this->fillCommonParams($params);
		$json = $this->request($params);
		$response = json_decode($json);
	
		if (!empty($response->error)) {
			$this->error = $response->error->error_msg;
			return null;
		}
		// TODO: make a transaction info
		$response->response;		
	}
	
	private function request(&$params) {
		if (empty($this->server)) {
			return false;
		}

		$url_parsed = parse_url($this->server);

        $host = $url_parsed["host"];
		$port = 80;
		
		$path = $url_parsed["path"];
		
		if ( empty( $path ) ) {
			$path="/";
		}

		/*if ( $url_parsed['query'] != "" ) {
			$path .= "?";
			// URL-encode the query (encode '@', ' ', etc)
			$query_str = $url_parsed["query"];
			$query_params = explode('&', $query_str);
			foreach ($query_params as $param) {
				 list($name, $value) = explode('=', $param, 2);
				 $params[$name] = $value;
			}
		}*/
		
		$path .= ("?" . http_build_query($params));
		
		$out = "GET $path HTTP/1.0\r\nHost: $host\r\n\r\n";
		$fp = fsockopen( $host, $port, $errno, $errstr, 30 );

		if ( $fp ) {
			fwrite( $fp, $out );

			$return = '';
		
			while ( !feof( $fp ) ) {
				$return .= fgets($fp, 1024);
			}
			fclose( $fp );
			return $this->getXmlResponse($return);
		} else {
			return null;
		}		
	}
	
	private function getXmlResponse($response) {
		$content = '';
		$str = strtok($response, "\n");
		$h = null;
		
		while ($str !== false) {
			if ($h and trim($str) === '') {
				$h = false;
				continue;
			}
			if ($h !== false and false !== strpos($str, ':')) {
				// skip headers
				$h = true;
			}
			if ($h === false) {
				$content .= $str."\n";
			}
			$str = strtok("\n");
		}
		return trim($content);
	}
}
?>